﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Com.AAS.Toolbox.DataMirror.Server.Handler.Impl
{
    /******************************************
     * 
     * 监控指定目录下的文件实时变换情况
     * 
     ******************************************/
    class FileSystemMonitorHandlerImpl : BaseHandlerImpl, FileSystemMonitorHandler
    {
        private DirectoryInfo rootDirInfo = null;

        #region FileSystemMonitorHandler 成员
        
        public void DoMonitor(string dir)
        {
            rootDirInfo = new DirectoryInfo(dir);
            if (!rootDirInfo.Exists)
                rootDirInfo.Create();

            // 文件监控
            FileSystemWatcher watcher = new FileSystemWatcher();
            watcher.Path = dir;
            watcher.Filter = "*.*";
            watcher.Changed += new FileSystemEventHandler(OnProcess);
            watcher.Created += new FileSystemEventHandler(OnProcess);
            watcher.Deleted += new FileSystemEventHandler(OnProcess);
            watcher.Renamed += new RenamedEventHandler(OnRenamed);
            watcher.EnableRaisingEvents = true;
            watcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime |
                NotifyFilters.DirectoryName | NotifyFilters.FileName |
                NotifyFilters.LastAccess    | NotifyFilters.LastWrite |
                NotifyFilters.Security | NotifyFilters.Size;
            watcher.IncludeSubdirectories = true;
        }

        private void OnProcess(object source, FileSystemEventArgs e)
        {
            MonitorEvent newEvent = new MonitorEvent();

            if (e.ChangeType == WatcherChangeTypes.Created)
                newEvent.EventType = EventType.DATA_SYNC_ADD;
            else if (e.ChangeType == WatcherChangeTypes.Changed)
                newEvent.EventType = EventType.DATA_SYNC_UPD;
            else if (e.ChangeType == WatcherChangeTypes.Deleted)
                newEvent.EventType = EventType.DATA_SYNC_DEL;
            else
                return;

            newEvent.EventState = EventState.READY;
            newEvent.EntityData = new EntityData();
            if (File.Exists(e.FullPath))
                newEvent.EntityData.EntityType = EntityType.FILE;
            if (Directory.Exists(e.FullPath))
                newEvent.EntityData.EntityType = EntityType.DIRECTORY;

            newEvent.EntityData.OriginalMonitorPath = rootDirInfo.FullName;
            newEvent.EntityData.OriginalFullPath = e.FullPath;
            newEvent.EntityData.OriginalName = e.Name;

            OnEventNotie(newEvent);
            
            OnEventNotie(new MonitorEvent(new LogData(
                LogLevel.I, "monitor " + newEvent.EventType + " file : " + rootDirInfo.Name, e.FullPath)));
        }

        private void OnRenamed(object source, RenamedEventArgs e)
        {
            MonitorEvent newEvent = new MonitorEvent();
            newEvent.EventType = EventType.DATA_SYNC_REN;
            newEvent.EventState = EventState.READY;
            newEvent.EntityData = new EntityData();
            if (File.Exists(e.FullPath))
            {
                newEvent.EntityData.EntityType = EntityType.FILE;
            }
            if (Directory.Exists(e.FullPath))
                newEvent.EntityData.EntityType = EntityType.DIRECTORY;

            newEvent.EntityData.OriginalMonitorPath = rootDirInfo.FullName;
            newEvent.EntityData.OriginalFullPath = e.FullPath;
            newEvent.EntityData.OriginalName = e.Name;
            newEvent.EntityData.OldOriginalFullPath = e.OldFullPath;
            newEvent.EntityData.OldOriginalName = e.OldName;
            
            // 存在目录和文件的重名名
            // 文件重命名：先触发Renamed事件后触发process事件
            OnEventNotie(newEvent);

            OnEventNotie(new MonitorEvent(new LogData(
                    LogLevel.I, "monitor rename file : " + e.OldName + "->" + e.Name, e.FullPath)));
        }

        #endregion

    }
}
